﻿// -- MVC4WPF
// -- Copyright © 2009 Information Control Corporation
// -- Revision History:
// -- Version 0.9.0.0 First codeplex release  - Stephen Giffin

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using System.ComponentModel;

namespace MVC4WPF
{
    /// <summary>
    /// Base class that implements all the logic for event handling, properties, logic for methods exposed by IWPFView. 
    /// </summary>
    public class WPFViewPage:Page, IWPFViewPage 
    {
        #region Constructor

        /// <summary>
        /// Base constructor that will register subscriptions to events on the base window clase. 
        /// This will also implement all the base methods.
        /// </summary>
        public WPFViewPage()
        {
            try
            {

              
            }
            catch
            {
                //Swallowing exceptions during construction
            }

        }
        #endregion

        #region IWPFView Members

        /// <summary>
        /// Returns the current Dispatcher for this view.
        /// </summary>
        Dispatcher IWPFView.ViewDispatcher
        {
            get { return base.Dispatcher; }
        }

        /// <summary>
        /// Similar to the constructor of the view, 
        /// this helper method is used to set the view into a default state. 
        /// This is generally used when you want to reset the view, 
        /// or when you need to do additional configuration after supported data has been loaded.
        /// The hosting controller usally calls this method.
        /// </summary>
        void IWPFView.ConfigureView()
        {
            ConfigureView();
        }

        #endregion

        #region IWPFView helper methods

        /// <summary>
        /// Similar to the constructor of the view, 
        /// this helper method is used to set the view into a default state. 
        /// This is generally used when you want to reset the view, 
        /// or when you need to do additional configuration after supported data has been loaded.
        /// </summary>
        /// <remarks>
        /// This method is implemented with no functionality by default. 
        /// You can overload this method and add configuration functionality.
        /// </remarks>
        protected virtual void ConfigureView()
        {
            //Intentinally Blank
        }

        #endregion

        #region Implemention of Interface - INotifyPropertyChanged

        #region Implementation of event - PropertyChanged

        /// <summary>
        /// Local variable that is the event handler for the event 'PropertyChanged'.
        /// </summary>
        private PropertyChangedEventHandler _propertyChanged;

        /// <summary>
        /// Local variable that is the lock object for the event 'PropertyChanged', this is included for thread safety.
        /// </summary>
        private object _propertyChangedEventLock = new object();

        /// <summary>
        /// Subscribers to this event will be notified when a property has been changed, and the name of the changed property.
        /// </summary>
        event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
        {
            add
            {
                lock (_propertyChangedEventLock)
                {
                    _propertyChanged += value;
                }
            }

            remove
            {
                if (_propertyChangedEventLock != null)
                {
                    lock (_propertyChangedEventLock)
                    {
                        _propertyChanged -= value;
                    }
                }
            }
        }

        #endregion

        #region Helper methods for PropertyChanged

        /// <summary>
        /// Helper method that will On the 'PropertyChanged' event if there are any subscribers. This method will invoke the event with a standard invoke.
        /// </summary>
        /// <param name="sender">The source caller of the event.</param>
        /// <param name="e">The event arguments to be Ond with the event.</param>
        protected void OnPropertyChangedEvent(object sender, PropertyChangedEventArgs e)
        {

            if (_propertyChanged != null)
            {
                _propertyChanged.Invoke(sender, e);
            }
        }

        /// <summary>
        /// Helper method that will release the resources for the event "PropertyChanged"
        /// </summary>
        private void ReleasePropertyChangedEvent()
        {
            _propertyChanged = null;
            _propertyChangedEventLock = null;
        }

        /// <summary>
        /// This will alert all subscribers to the property changed event that a property has changed.
        /// </summary>
        /// <param name="propertyName">Name of the property that has changed.</param>
        protected void OnPropertyChanged(string propertyName)
        {
            this.OnPropertyChangedEvent(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        #endregion

        #region Implementation of Interface - INotifyPropertyChanging

        #region Implementation of event - PropertyChanging

        /// <summary>
        /// Local variable that is the event handler for the event 'PropertyChanging'.
        /// </summary>
        private PropertyChangingEventHandler _propertyChanging;

        /// <summary>
        /// Local variable that is the lock object for the event 'PropertyChanging', this is included for thread safety.
        /// </summary>
        private object _propertyChangingEventLock = new object();

        /// <summary>
        /// Subscribers to this event will be notified when a property is about to be changed, and the name of the changing property. 
        /// This is not a cancable event.
        /// </summary>
        event PropertyChangingEventHandler INotifyPropertyChanging.PropertyChanging
        {
            add
            {
                lock (_propertyChangingEventLock)
                {
                    _propertyChanging += value;
                }
            }

            remove
            {
                if (_propertyChangingEventLock != null)
                {
                    lock (_propertyChangingEventLock)
                    {
                        _propertyChanging -= value;
                    }
                }
            }
        }

        #endregion

        #region Helper methods for PropertyChanging

        /// <summary>
        /// Helper method that will On the 'PropertyChanging' event if there are any subscribers. This method will invoke the event with a standard invoke.
        /// </summary>
        /// <param name="sender">The source caller of the event.</param>
        /// <param name="e">The event arguments to be Ond with the event.</param>
        protected void OnPropertyChangingEvent(object sender, PropertyChangingEventArgs e)
        {
            if (_propertyChanging != null)
            {
                _propertyChanging.Invoke(sender, e);
            }
        }

        /// <summary>
        /// Helper method that will release all resources used for the PropertyChanging event.
        /// </summary>
        private void ReleasePropertyChangingEvent()
        {
            _propertyChanging = null;
            _propertyChangingEventLock = null;
        }

        /// <summary>
        /// This will alert all subscribers to the PropertyChanging event that a property is about to change.
        /// </summary>
        /// <param name="propertyName">The name of the property that is about to change.</param>
        protected void OnPropertyChanging(string propertyName)
        {
            this.OnPropertyChangingEvent(this, new PropertyChangingEventArgs(propertyName));
        }

        #endregion

        #endregion

        #region ResourceManager

        /// <summary>
        /// Releases all resources used by the WPFViewUserControl base class.
        /// </summary>
        protected void ReleaseViewResources()
        {
            //Releasing the event handlers maintained by this class.
            ReleasePropertyChangedEvent();
            ReleasePropertyChangingEvent();
        }

        #endregion
    }
}